package middle.ground.utils;

import org.springframework.util.StringUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Hashtable;
import java.util.regex.Pattern;

/**
 * 身份证工具类
 *
 * @author jrl
 * @date 2020-02-20
 */
public class IdCardUtil{

	private static final Integer FIFTEEN_ID_CARD_LENGTH = 15;
	private static final Integer EIGHTEEN_ID_CARD_LENGTH = 18;
	private static SimpleDateFormat DATE_FORMATE = new SimpleDateFormat("yyyyMMdd");

	/**
	 * 验证18位身份证号码是否规范
	 *
	 * @param iDCardStr
	 * @return
	 */
	public static boolean validate(String iDCardStr) {
		if (iDCardStr.length() != EIGHTEEN_ID_CARD_LENGTH) {
			return false;
		}

		String pre17OfIdCard = iDCardStr.substring(0, 17);
		if (!isNumberStr(pre17OfIdCard)) {
			return false;
		}

		String strYear = pre17OfIdCard.substring(6, 10), strMonth = pre17OfIdCard.substring(10, 12),
				strDay = pre17OfIdCard.substring(12, 14), birthdayStr = strYear + "-" + strMonth + "-" + strDay;
		if (!isDate(birthdayStr)) {
			return false;
		}

		// 年龄范围1-150
		GregorianCalendar currentCalendar = new GregorianCalendar();
		if ((currentCalendar.get(Calendar.YEAR) - Integer.parseInt(strYear)) > 150
				|| (currentCalendar.getTime().getTime()
				- DateUtil.parseDate(strYear + "-" + strMonth + "-" + strDay).getTime()) < 0) {
			return false;
		}

		if (Integer.parseInt(strMonth) > 12 || Integer.parseInt(strMonth) == 0) {
			return false;
		}

		if (Integer.parseInt(strDay) > 31 || Integer.parseInt(strDay) == 0) {
			return false;
		}

		if (mapAreaCode().get(pre17OfIdCard.substring(0, 2)) == null) {
			return false;
		}

		if (!verifyLastCode(pre17OfIdCard, iDCardStr)) {
			return false;
		}

		return true;
	}

	public static String get18IdCardCode(String idCard15) {
		if (StringUtil.isBlank(idCard15) || idCard15.length() != FIFTEEN_ID_CARD_LENGTH) {
			throw new RuntimeException();
		}

		// 在原15位数身份证的第六位数后面插入19
		String id17 = idCard15.substring(0, 6) + "19" + idCard15.substring(6);

		return id17 + getVerifyCode(id17);
	}

	private static boolean verifyLastCode(String Ai, String IDStr) {
		return (Ai + getVerifyCode(IDStr)).equals(IDStr);
	}

	private static String getVerifyCode(String idCard) {
		String[] verifyCode = {"1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"};
		String[] Wi = {"7", "9", "10", "5", "8", "4", "2", "1", "6", "3", "7", "9", "10", "5", "8", "4", "2"};
		int sum = 0;

		for (int i = 0; i < 17; i++) {
			sum = sum + Integer.parseInt(String.valueOf(idCard.charAt(i))) * Integer.parseInt(Wi[i]);
		}

		int modValue = sum % 11;
		return verifyCode[modValue];
	}

	private static Hashtable<String, String> mapAreaCode() {
		return new Hashtable<String, String>(33){
			private static final long serialVersionUID = -2761532970092935966L;

			{
				put("11", "北京");
				put("12", "天津");
				put("13", "河北");
				put("14", "山西");
				put("15", "内蒙古");
				put("21", "辽宁");
				put("22", "吉林");
				put("23", "黑龙江");
				put("31", "上海");
				put("32", "江苏");
				put("33", "浙江");
				put("34", "安徽");
				put("35", "福建");
				put("36", "江西");
				put("37", "山东");
				put("41", "河南");
				put("42", "湖北");
				put("43", "湖南");
				put("44", "广东");
				put("45", "广西");
				put("46", "海南");
				put("50", "重庆");
				put("51", "四川");
				put("52", "贵州");
				put("53", "云南");
				put("54", "西藏");
				put("61", "陕西");
				put("62", "甘肃");
				put("63", "青海");
				put("64", "宁夏");
				put("65", "新疆");
				put("71", "台湾");
				put("81", "香港");
				put("82", "澳门");
				put("91", "国外");
			}
		};
	}

	private static boolean isNumberStr(String strNum) {
		return Pattern.compile("[0-9]*").matcher(strNum).matches();
	}

	public static boolean isDate(String strDate) {
		return Pattern.compile(
				"^((\\d{2}(([02468][048])|([13579][26]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])))))|(\\d{2}(([02468][1235679])|([13579][01345789]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|(1[0-9])|(2[0-8]))))))?$")
				.matcher(strDate).matches();
	}

	/**
	 * 根据身份证号获取性别
	 *
	 * @param iDCard
	 * @return 性别代码 2：男，1：
	 */
	public static Integer getSex(String iDCard) {
		if (StringUtils.hasText(iDCard)) {
			if (iDCard.length() == FIFTEEN_ID_CARD_LENGTH) {
				return Integer.parseInt(iDCard.substring(14, 15)) % 2 == 0 ? 2 : 1;
			} else if (iDCard.length() == EIGHTEEN_ID_CARD_LENGTH) {
				return Integer.parseInt(iDCard.substring(16).substring(0, 1)) % 2 == 0 ? 2 : 1;
			}
		}
		return null;
	}

	/**
	 * 根据身份证号获取年龄
	 *
	 * @param iDCard
	 * @return
	 */
	public static Integer getAge(String iDCard) {
		Integer age = 0;
		if (StringUtils.hasText(iDCard)) {
			if (iDCard.length() == FIFTEEN_ID_CARD_LENGTH) {
				// 身份证上的年份(15位身份证为1980年前的)
				String date = "19" + iDCard.substring(6, 12);
				try {
					return getAgeByBirth(DATE_FORMATE.parse(date));
				} catch (ParseException e) {
					e.printStackTrace();
				}
			} else if (iDCard.length() == EIGHTEEN_ID_CARD_LENGTH) {
				String date = iDCard.substring(6, 14);
				try {
					return getAgeByBirth(DATE_FORMATE.parse(date));
				} catch (ParseException e) {
					e.printStackTrace();
				}
			}
		}
		return age;
	}

	/**
	 * 获取出生日期 yyyy年MM月dd日
	 *
	 * @param IDCard
	 * @return xxxx年xx月xx日
	 */
	public static String getBirthday(String IDCard) {
		String birthday = "";
		String year = "";
		String month = "";
		String day = "";
		if (StringUtils.hasText(IDCard)) {
			if (IDCard.length() == FIFTEEN_ID_CARD_LENGTH) {
				// 身份证上的年份(15位身份证为1980年前的)
				year = "19" + IDCard.substring(6, 8);
				// 身份证上的月份
				month = IDCard.substring(8, 10);
				// 身份证上的日期
				day = IDCard.substring(10, 12);
			} else if (IDCard.length() == EIGHTEEN_ID_CARD_LENGTH) {
				// 身份证上的年份
				year = IDCard.substring(6).substring(0, 4);
				// 身份证上的月份
				month = IDCard.substring(10).substring(0, 2);
				// 身份证上的日期
				day = IDCard.substring(12).substring(0, 2);
			}
			birthday = year + "年" + month + "月" + day + "日";
		}
		return birthday;
	}

	/**
	 * 通过生日获取年龄
	 *
	 * @param birthday
	 * @return
	 */
	public static int getAgeByBirth(Date birthday) {
		Calendar birth = Calendar.getInstance();
		birth.setTime(birthday);

		Calendar now = Calendar.getInstance();
		int offsetYear = now.get(Calendar.YEAR) - birth.get(Calendar.YEAR);
		int offsetDay = now.get(Calendar.DAY_OF_YEAR) - birth.get(Calendar.DAY_OF_YEAR);
		if (offsetDay < 0 && offsetYear > 0) {
			offsetYear = offsetYear - 1;
		}
		return offsetYear;
	}
}
